package yxy.game.pm2.module.kow;

import java.util.*;

import com.alibaba.fastjson.JSON;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;

import org.joda.time.format.DateTimeFormat;
import yxy.apple.logger.Logger;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.function;
import yxy.cherry.data.bean.txdyjingcai;
import yxy.cherry.data.bean.txdyrankreward;
import yxy.cherry.data.function.Function;
import yxy.cherry.data.string.GameString;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.area.AreaGroupBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.RedisLock;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.bean.timeline.FutureRunnable;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.BattleModule;
import yxy.game.pm2.module.kow.KowHandle.KowFinalCode;
import yxy.game.pm2.module.kow.KowHandle.KowRankLevel;
import yxy.game.pm2.module.kow.KowHandle.KowStepEnum;
import yxy.game.pm2.module.mail.MailHandle;
import yxy.game.pm2.module.mail.MailTypeEnum;
import yxy.game.pm2.module.player.RankPlayerPower;
//天下第一 结算
public class KowFuture extends FutureRunnable {
    protected static Logger logger = Logger.create(KowFuture.class);

    @Override
    public void init() {
        handle();
    }

    @Override
    public void tick() {
        handle();
    }

    @Override
    public long period() {
        return DateTimeConstants.MILLIS_PER_MINUTE * 5;// 5分钟一刷
    }

    private void handle() {
        Collection<AreaGroupBean> areaGroupBeans = AreaGroupBean.all();
        for (AreaGroupBean areaGroupBean : areaGroupBeans) {
            RedisLock lock = KowModule.lock(areaGroupBean.getGroupId());
            try {
                if (lock.tryLock()) {
                    KowModule kowModule = KowModule.get(areaGroupBean.getGroupId());
                    update(kowModule);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

    }

    public void update(KowModule kowModule) {
        DateTime now = DateTime.now();
        DateTime stateTime = kowModule.getStateTimes().get(kowModule.getState());
        DateTime endTime = kowModule.getStateTimes().get(KowStepEnum.STEP_OFFSEASON); //该轮活动结束时间
        logger.info("天下第一，%s,当前状态时间：%s,当前时间：%s,赛季结束时间：%s",
                kowModule.getAreaGroupId(),
                stateTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")),
                now.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")),
                endTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
        );

        if (now.isAfter(endTime)) {
            kowModule.resetState(now);
            kowModule.set();
            return;
        }
        while (now.isAfter(stateTime)) {
            KowStepEnum nextState = kowModule.getState().getNext(); //下一轮的状态
            try {
                updateState(kowModule, nextState);
                if (!nextState.equals(KowStepEnum.STEP_PRE) && !kowModule.isRunning()) {
                    kowModule.resetState(now);
                    kowModule.set();
                    return;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            kowModule.setState(nextState);
            stateTime = kowModule.getStateTimes().get(nextState);
            logger.info(DateTime.now() + "::%s区，天下第一状态::	" + nextState, kowModule.getAreaGroupId());
        }

        kowModule.set();
    }

    private void updateState(KowModule kowModule, KowStepEnum state) {
        switch (state) {
            case STEP_PRE:
                break;
            case STEP_GROUP_1: {
                boolean ok = initGroup(kowModule);
                if (ok) {
                    kowModule.setRunning(true);
                    kowModule.set();
                }
            }
            break;
            case STEP_GROUP_1_SET:
                break;
            case STEP_GROUP_2:
                break;
            case STEP_GROUP_2_SET:
                break;
            case STEP_GROUP_3:
                break;
            case STEP_GROUP_3_SET:
                break;
            case STEP_GROUP_4:
                break;
            case STEP_GROUP_4_SET:
                break;
            case STEP_QUARTER: {
                initQuarter(kowModule);
            }
            break;
            case STEP_SEMI: {
                initSemi(kowModule);
            }
            break;
            case STEP_FINAL: {
                initFinal(kowModule);
            }
            break;
            case STEP_OFFSEASON: {
                handleFinal(kowModule);
            }
            break;
            default:
                break;
        }
    }

    /**
     * 初始化八强
     */
    private void initQuarter(KowModule kowModule) {
        kowModule.getFinals().clear();
        kowModule.addFinal(newFinal(kowModule.getAreaGroupId(), KowFinalCode.F12, 1, 2));
        kowModule.addFinal(newFinal(kowModule.getAreaGroupId(), KowFinalCode.F34, 3, 4));
        kowModule.addFinal(newFinal(kowModule.getAreaGroupId(), KowFinalCode.F56, 5, 6));
        kowModule.addFinal(newFinal(kowModule.getAreaGroupId(), KowFinalCode.F78, 7, 8));
        kowModule.set();
    }

    private KowFinal newFinal(int areaGroupId, KowFinalCode finalCode, int g1, int g2) {
        RankKowGroup group1 = new RankKowGroup(areaGroupId, g1);
        RankKowGroup group2 = new RankKowGroup(areaGroupId, g2);
        RankEntry entry1 = group1.best();
        RankEntry entry2 = group2.best();

        return newFinal(finalCode, entry1.getKey(), entry2.getKey());
    }

    private KowFinal newFinal(KowFinalCode finalCode, String playerCode1, String playerCode2) {
        KowFinal kowFinal = new KowFinal();
        KowFinalPlayer finalPlayer1 = new KowFinalPlayer();
        finalPlayer1.setPlayerCode(playerCode1);
        kowFinal.setPlayer1(finalPlayer1);

        KowFinalPlayer finalPlayer2 = new KowFinalPlayer();
        finalPlayer2.setPlayerCode(playerCode2);
        kowFinal.setPlayer2(finalPlayer2);

        kowFinal.setFinalCode(finalCode);

        KowPlayerModule playerModule1 = KowPlayerModule.get(playerCode1);
        KowPlayerModule playerModule2 = KowPlayerModule.get(playerCode2);
        try {
            if (playerModule1.tryLock() && playerModule2.tryLock()) {
                switch (finalCode) {
                    case F12:
                    case F34:
                    case F56:
                    case F78:
                        playerModule1.rankLevelUp(KowRankLevel.Eight);
                        playerModule2.rankLevelUp(KowRankLevel.Eight);
                        break;
                    case F1256:
                    case F3478:
                        playerModule1.rankLevelUp(KowRankLevel.Four);
                        playerModule2.rankLevelUp(KowRankLevel.Four);
                        break;
                    case FINAL:
                        playerModule1.rankLevelUp(KowRankLevel.RunnerUp);
                        playerModule2.rankLevelUp(KowRankLevel.RunnerUp);
                        break;
                    default:
                        break;
                }
                playerModule1.set();
                playerModule2.set();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            playerModule1.unlock();
            playerModule2.unlock();
        }

        return kowFinal;
    }

    /**
     * 初始化四强
     */
    private void initSemi(KowModule kowModule) {
        logger.info("天下第一:initSemi:%s", kowModule.getAreaGroupId());
        // 八强战
        KowFinal final12 = handleFinalBattle(kowModule, KowFinalCode.F12);
        KowFinal final34 = handleFinalBattle(kowModule, KowFinalCode.F34);
        KowFinal final56 = handleFinalBattle(kowModule, KowFinalCode.F56);
        KowFinal final78 = handleFinalBattle(kowModule, KowFinalCode.F78);

        kowModule.addFinal(newFinal(KowFinalCode.F1256, final12.getWinner().getPlayerCode(), final56.getWinner().getPlayerCode()));
        kowModule.addFinal(newFinal(KowFinalCode.F3478, final34.getWinner().getPlayerCode(), final78.getWinner().getPlayerCode()));
        kowModule.set();
    }

    /**
     * 初始化决赛
     */
    private void initFinal(KowModule kowModule) {
        logger.info("天下第一:initFinal:%s", kowModule.getAreaGroupId());
        // 四强战
        KowFinal final1256 = handleFinalBattle(kowModule, KowFinalCode.F1256);
        KowFinal final3478 = handleFinalBattle(kowModule, KowFinalCode.F3478);

        kowModule.addFinal(newFinal(KowFinalCode.FINAL, final1256.getWinner().getPlayerCode(), final3478.getWinner().getPlayerCode()));
        kowModule.set();
    }

    /**
     * 决赛
     */
    private void handleFinal(KowModule kowModule) {
        logger.info("天下第一:handleFinal:%s", kowModule.getAreaGroupId());
        KowFinal kowFinal = handleFinalBattle(kowModule, KowFinalCode.FINAL);
        kowModule.set();

        KowFinal final1256 = kowModule.getFinals().get(KowFinalCode.F1256);
        KowFinal final3478 = kowModule.getFinals().get(KowFinalCode.F3478);
        KowFinal final12 = kowModule.getFinals().get(KowFinalCode.F12);
        KowFinal final34 = kowModule.getFinals().get(KowFinalCode.F34);
        KowFinal final56 = kowModule.getFinals().get(KowFinalCode.F56);
        KowFinal final78 = kowModule.getFinals().get(KowFinalCode.F78);

        String winner = kowFinal.getWinner().getPlayerCode();
        String runner = kowFinal.oppo(kowFinal.getWinner().getPlayerCode()).getPlayerCode();
        String four1 = final1256.oppo(final1256.getWinner().getPlayerCode()).getPlayerCode();
        String four2 = final3478.oppo(final3478.getWinner().getPlayerCode()).getPlayerCode();
        String eight1 = final12.oppo(final12.getWinner().getPlayerCode()).getPlayerCode();
        String eight2 = final34.oppo(final34.getWinner().getPlayerCode()).getPlayerCode();
        String eight3 = final56.oppo(final56.getWinner().getPlayerCode()).getPlayerCode();
        String eight4 = final78.oppo(final78.getWinner().getPlayerCode()).getPlayerCode();

        RankKowKing rankKowKing = new RankKowKing(kowModule.getAreaGroupId());
        Collection<RankEntry> 原霸主 = rankKowKing.all();
        rankKowKing.clear();
        rankKowKing.put(winner, KowRankLevel.Winner.getNumber());
        rankKowKing.put(runner, KowRankLevel.RunnerUp.getNumber());
        rankKowKing.put(four1, KowRankLevel.Four.getNumber());
        rankKowKing.put(four2, KowRankLevel.Four.getNumber());

        KowPlayerModule winnerModule = KowPlayerModule.get(winner);
        try {
            if (winnerModule.tryLock()) {
                winnerModule.rankLevelUp(KowRankLevel.Winner);
                winnerModule.set();
            }
        } catch (Exception e) {
        } finally {
            winnerModule.unlock();
        }

        // 邮件发奖
        {
            rewardKing(winner, KowRankLevel.Winner);
            rewardKing(runner, KowRankLevel.RunnerUp);
            rewardKing(four1, KowRankLevel.Four);
            rewardKing(four2, KowRankLevel.Four);
            rewardKing(eight1, KowRankLevel.Eight);
            rewardKing(eight2, KowRankLevel.Eight);
            rewardKing(eight3, KowRankLevel.Eight);
            rewardKing(eight4, KowRankLevel.Eight);
            //todo 小组赛的8个组1-10名也对应发奖励
            sendRewardForGroup(kowModule.getAreaGroupId());

        }

        {
            // 原霸主摘掉称号
            for (RankEntry entry : 原霸主) {
                int level = entry.getValue().intValue();
                String playerCode = entry.getKey();
                int removeTitle = 0;
                switch (level) {
                    case 1:// 冠军
                        if (!playerCode.equals(winner)) {
                            removeTitle = 301;
                        }
                        break;
                    case 2:// 亚军
                        if (!playerCode.equals(runner)) {
                            removeTitle = 302;
                        }
                        break;
                    case 3:// 四强
                        if (!playerCode.equals(four1) && !playerCode.equals(four2)) {
                            removeTitle = 303;
                        }
                        break;
                }
                if (removeTitle <= 0) {
                    continue;
                }
                try {
                    new CurrencyHandle().cost(playerCode, CCReason.天下第一, Currency.create(CurrencyType.CT_称号, removeTitle, 1));
                } catch (CurrencyNotEnoughException e) {
                }
            }
        }

    }


    /**
     * 小组赛的8个组1-10名也对应发奖励
     *
     * @param areaGroupId
     */
    private void sendRewardForGroup(int areaGroupId) {
        try {
            for (int i = 1; i <= 8; i++) {
                RankKowGroup group = new RankKowGroup(areaGroupId, i);
                rewardKing(group.first(), KowRankLevel.GroupFirst);
                rewardKing(group.second(), KowRankLevel.GroupSecond);
                rewardKing(group.third(), KowRankLevel.GroupThird);
                for (String playerCode : group.fourthToTenth()) {
                    rewardKing(playerCode, KowRankLevel.GroupFourthToTenth);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始分组
     */
    private boolean initGroup(KowModule kowModule) {
        if (kowModule.isRunning()) {
            return false;
        }
        int minSize = 32; //@TODO:满足多少人才开赛
        int maxSize = 100; //每个排行榜最大参赛人数

        // 模块检查
        function functiondata = DataCenter.getData(Function.天下第一.getId(), function.class);
        logger.info("天下第一：functiondata:%s", functiondata);
        if (functiondata == null) {
            return false;
        }

        AreaGroupBean areaGroupBean = AreaGroupBean.get(kowModule.getAreaGroupId());
        List<AreaBean> areaBeanList = new ArrayList<>();
        //取战区内的区列表
        areaGroupBean.getAreaList().forEach(areaId -> {
            areaBeanList.add(AreaBean.get(Integer.parseInt(areaId)));
        });

        ArrayList<AreaBean> areaIn = new ArrayList<>();
        for (AreaBean areaBean : areaBeanList) {
            if (areaBean == null || areaBean.getWorldLevel() < functiondata.getWordlv()) {
                continue;
            }
            areaIn.add(areaBean);
        }
        if (areaIn.size() <= 0) {
            logger.error("天下第一：战区的区数量不达标：%s", kowModule.getAreaGroupId());
            return false;// 没有一个达标的区
        }

        ArrayList<RankEntry> range = new ArrayList<>();
        for (AreaBean areaBean : areaIn) {
            // 找到玩家进行分组
            RankPlayerPower rank = new RankPlayerPower(areaBean);
            Collection<RankEntry> ranges = rank.range(1, maxSize); //@TODO:TEST
            range.addAll(ranges);

            //---------bebug用
            ArrayList<String> players = new ArrayList<>();
            ranges.forEach(rankEntry -> {
                players.add(rankEntry.getKey() + ":" + rankEntry.getValue());
            });
            logger.info("天下第一：%s战区，%s区，参赛人员/区战力榜,%s", kowModule.getAreaGroupId(), areaBean.getAreaId(), JSON.toJSONString(players));
        }
        if (range.size() < minSize) {
            logger.error("天下第一：%s战区,参赛人数不够,%s", kowModule.getAreaGroupId(), range.size());
            return false;
        }

        // 按战力排序
        range.sort(new Comparator<RankEntry>() {
            @Override
            public int compare(RankEntry o1, RankEntry o2) {
                if (o1.getValue() < o2.getValue()) {
                    return 1;
                }
                return -1;
            }
        });

        // 参赛者等级检查
//        int qualifiedLevel = functiondata.getPlayerlv();
//        int n = 0;
//        for (RankEntry entry : range) {
//            String playerCode = entry.getKey();
//            PlayerBean playerBean = PlayerBean.get(playerCode);
//            if (playerBean == null) continue;
//            if (playerBean.getLevel() < qualifiedLevel) {
//                logger.error("天下第一：玩家等级不够::" + playerBean.getCode() + "::" + playerBean.getLevel());
//                return false;// 战力榜前80名中如果有没到达等级的玩家 则不予开赛
//            }
//            if (n++ >= maxSize) {
//                break;
//            }
//        }

        RankKowGroup[] groups = new RankKowGroup[8];
        for (int i = 0; i < groups.length; i++) {
            RankKowGroup group = new RankKowGroup(kowModule.getAreaGroupId(), i + 1);
            group.clear();
            groups[i] = group;
        }
        ArrayList<Integer> lowgroup = new ArrayList<>();
        for (int i = groups.length; i < range.size(); i++) {
            lowgroup.add(i % 8);
        }
        Collections.shuffle(lowgroup);
        int i = 0;
        for (RankEntry entry : range) {
            String playCode = entry.getKey();
            if (i < topgroup.length) {
                groups[topgroup[i] - 1].put(playCode, 1000 - i);// 初始分数
            } else {
                int g = lowgroup.get(i - 8);
                groups[g].put(playCode, 1000 - i);
            }
            i++;
        }
        KowHandle handle = new KowHandle();
        for (RankKowGroup group : groups) {
            for (String playerCode : group.allKeys()) {
                KowPlayerModule playerModule = KowPlayerModule.get(playerCode);
                try {
                    if (playerModule.tryLock()) {
                        playerModule.setCode(kowModule.getCode());
                        playerModule.setGroup(group.getGroupId());
                        playerModule.setNowLevel(KowRankLevel.Group);
                        handle.refreshOppo(playerModule, group);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    playerModule.unlock();
                }
            }
        }
        return true;
    }

    static private int[] topgroup = {1, 8, 3, 6, 2, 7, 4, 5};

    /**
     * 决赛战斗
     */
    private KowFinal handleFinalBattle(KowModule kowModule, KowFinalCode finalCode) {
        KowFinal kowFinal = kowModule.getFinals().get(finalCode);

        BattleModule battleModule = new KowHandle().handleBattle(kowFinal.getPlayer1().getPlayerCode(), kowFinal.getPlayer2().getPlayerCode());

        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        kowFinal.setWinner(isWin ? kowFinal.getPlayer1() : kowFinal.getPlayer2());

        // 处理录像
        {
            String recordCode = String.format("kowRec:%s:%s", kowModule.getAreaGroupId(), finalCode.name());
            battleModule.saveRecord(recordCode);
            kowFinal.setRecord(recordCode);
        }

        // 结算竞猜
        rewardFans(kowModule, kowFinal);

        return kowFinal;
    }

    private void rewardKing(String playerCode, KowRankLevel rankLevel) {
        String rank = GameString.天下第一名次冠军().getText();
        int dataId = 101;// 冠军
        switch (rankLevel) {
            case Winner:
                break;
            case RunnerUp:
                dataId = 102;// 亚军
                rank = GameString.天下第一名次亚军().getText();
                break;
            case Four:
                dataId = 103;// 四强
                rank = GameString.天下第一名次四强().getText();
                break;
            case Eight:
                dataId = 104;// 八强
                rank = GameString.天下第一名次八强().getText();
                break;
            case GroupFirst:
                dataId = 105;// 小组赛第一
                rank = GameString.天下第一小组赛第一名().getText();
                break;
            case GroupSecond:
                dataId = 106;// 小组赛第二
                rank = GameString.天下第一小组赛第二名().getText();
                break;
            case GroupThird:
                dataId = 107;// 小组赛第三
                rank = GameString.天下第一小组赛第三名().getText();
                break;
            case GroupFourthToTenth:
                dataId = 108;// 小组赛四到十
                rank = GameString.天下第一小组赛前十名().getText();
                break;
            default:
                return;
        }
        txdyrankreward data = DataCenter.getData(dataId, txdyrankreward.class);
        Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));

        String title = GameString.天下第一排行奖励_titl(rank).getText();
        String content = GameString.天下第一排行奖励_msg(rank).getText();
        new MailHandle().sendMail(playerCode, MailTypeEnum.Mail, title, content, CCReason.天下第一, rewards);
    }

    private void rewardFans(KowModule kowModule, final KowFinal kowFinal) {
        logger.info("天下第一：竞猜奖励发放:%s:%s:begin", kowModule.getAreaGroupId(), kowModule.getState());
//		ThreadPoolManager.getInstance().execute(new Runnable() {
//
//			@Override
//			public void run() {
        txdyjingcai data = kowFinal.data();
        Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
        String title = GameString.天下第一竞猜奖励_titl().getText();
        String content = GameString.天下第一竞猜奖励_msg().getText();
        for (String playerCode : kowFinal.getWinner().getFans()) {
            logger.info("天下第一：竞猜奖励发放:%s", playerCode);
            new MailHandle().sendMail(playerCode, MailTypeEnum.Mail, title, content, CCReason.天下第一, rewards);
        }
        logger.info("天下第一：竞猜奖励发放:%s:%s:end", kowModule.getAreaGroupId(), kowModule.getState());
//			}
//		});
    }

}
